package service;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import model.League;
import model.User;
import org.springframework.transaction.annotation.Transactional;
import exceptions.DataException;
import exceptions.LeagueNotFoundException;
import exceptions.LeagueRestrictionException;
import exceptions.UserNotFoundException;

/**
 * Interface for a LeagueService..
 * @author Andre Melo
 * @author Marcus Leite 
 * @author Sergio Danilo
 *
 */
@Transactional
public interface LeagueService {
	
	/**
	 * Change some league attribute, that can be: 
	 * League's name or league operator 
	 * @param id League's ID
	 * @param attribute The attribute that will be changed 
	 * @param value The new value for the attribute
	 * @throws DataException Exception for data
	 * @throws IllegalAccessException Exception for illeal access
	 * @throws InvocationTargetException Exception for invocation target
	 * @throws LeagueRestrictionException Exception for league restriction
	 */
	 void changeLeagueAttribute(String idLeague, String attribute, String value) throws DataException, IllegalAccessException, InvocationTargetException, LeagueRestrictionException;
	
	/**
	 * Create a new league with your operator
	 * @param name The name of the league
	 * @param operatorId The operator of the league
	 * @return The ID of the league
	 * @throws DataException
	 * @throws LeagueRestrictionException
	 */
	 Integer createLeague(String name, Integer operatorId) throws DataException, LeagueRestrictionException;
	
	/**
	 * Delete a league with ID received
	 * @param id League's ID
	 * @return The removed league
	 */
	 League delete(Integer id);
	
	/**
	 * Delete all existing leagues 
	 */
	 void deleteAll();
	
	/**
	 * Find the league by received ID
	 * @param id The ID of the league
	 * @return The wanted league
	 */
	 League findById(Integer id);
	
	/**
	 * Find the league by your name
	 * @param name The name of the league
	 * @return The wanted league 
	 * @throws LeagueNotFoundException
	 */
	 List<String> findLeague(String name) throws LeagueNotFoundException;
	
	/**
	 * Return some league attribute by your name 
	 * @param id The ID of the league
	 * @param attribute The name of the attribute 
	 * @return The required attribute
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws NoSuchMethodException
	 */
	 String getLeagueAttribute(String id, String attribute) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException;
	
	/**
	 * Return the members of the league
	 * @param leagueId The ID of the league
	 * @return The users of the league
	 * @throws LeagueNotFoundException
	 */
	 List<User> getLeagueMembers(Integer leagueId) throws LeagueNotFoundException;

	/**
	 * Return the players of the league
	 * @param userId The ID of the user
	 * @return The players of the league
	 * @throws UserNotFoundException
	 * @throws LeagueNotFoundException
	 */
	 List<League> getPlayerLeagues(Integer userId) throws UserNotFoundException, LeagueNotFoundException;

	/**
	 * Returns some user league attribute
	 * @param userId The ID of the user 
	 * @param leagueId The ID of the league
	 * @param attribute The name of the attribute
	 * @return The required attribute
	 * @throws UserNotFoundException
	 * @throws LeagueNotFoundException
	 * @throws DataException
	 * @throws LeagueRestrictionException
	 */
	 String getUserLeagueAttribute(Integer userId, Integer leagueId, String attribute) throws UserNotFoundException, LeagueNotFoundException, DataException, LeagueRestrictionException;
	
	/**
	 * Verify if user is a league's member
	 * @param userId The ID of the user
	 * @param leagueId The ID of the league 
	 * @return True if user is a league's member, false otherwise
	 * @throws UserNotFoundException
	 * @throws LeagueNotFoundException
	 */
	 boolean isLeagueMember(Integer userId, Integer leagueId) throws UserNotFoundException, LeagueNotFoundException;

	/**
	 * Method for user joined in the league
	 * @param userId The ID of the user
	 * @param leagueId The ID of the league
	 * @param initialHandicap The initial handicap of the user
	 * @throws DataException
	 * @throws LeagueNotFoundException
	 * @throws LeagueRestrictionException
	 * @throws UserNotFoundException
	 */
	 void joinLeague(Integer userId, Integer leagueId, Integer initialHandicap) throws DataException, LeagueNotFoundException, LeagueRestrictionException, UserNotFoundException ;
	
	/**
	 * User can be leave the league by this method
	 * @param userId The ID of the user
	 * @param leagueId The ID of the league
	 * @throws LeagueRestrictionException
	 * @throws UserNotFoundException
	 * @throws LeagueNotFoundException
	 */
	 void leaveLeague(Integer userId, Integer leagueId) throws LeagueRestrictionException, UserNotFoundException, LeagueNotFoundException;
	
	/**
	 * List all existing leagues
	 * @return A list with all existing leagues
	 */
	 List<League> listAll();
	
	/**
	 * Save the league in a list
	 * @param league The saved league 
	 * @param operatorId The ID of the operator
	 * @return The league's ID
	 */
	 Integer save(League league, Integer operatorId);
	
	/**
	 * Uptade a league
	 * @param league The updated league
	 */
	 void update(League league);
	
	/**
	 * Return all leagues.
	 * @return All leagues.
	 */
	 List<League> getAllLeagues();

	/**
	 * Get the instance of UserService.
	 * @return Instance of UserService.
	 */
	 UserService getUserService();

	/**
	 * Set the instance of UserService.
	 * @param userService Instance of UserService.
	 */
	 void setUserService(UserService userService);

	/**
	 * Verify the league existence
	 * @param leagueId The ID of the league
	 * @return True if league existence, false otherwise
	 */
	 boolean verifyLeagueExistence(Integer leagueId);
	
}
